<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vite与Vue3核心指南 | 从入门到精通</title>
  <!-- 引入外部资源 -->
  <script src="https://cdn.tailwindcss.com"></script>
  <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">

  <!-- 配置Tailwind -->
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            primary: '#42b983', // Vue绿色作为主色调
            secondary: '#646cff', // Vite紫色作为辅助色
            dark: '#1e293b',
            light: '#f8fafc'
          },
          fontFamily: {
            sans: ['Inter', 'system-ui', 'sans-serif'],
            mono: ['Fira Code', 'monospace']
          },
        },
      }
    }
  </script>

  <!-- 自定义样式 -->
  <style type="text/tailwindcss">
    @layer utilities {
      .content-auto {
        content-visibility: auto;
      }
      .text-shadow {
        text-shadow: 0 2px 4px rgba(0,0,0,0.1);
      }
      .transition-smooth {
        transition: all 0.3s ease-in-out;
      }
      .scrollbar-hide::-webkit-scrollbar {
        display: none;
      }
      .code-block {
        @apply bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm my-4 font-mono;
      }
    }
  </style>
</head>

<body class="bg-gray-50 text-gray-800 font-sans">
  <!-- 导航栏 -->
  <header id="navbar" class="fixed w-full bg-white/90 backdrop-blur-sm shadow-sm z-50 transition-smooth">
    <div class="container mx-auto px-4 sm:px-6 lg:px-8">
      <div class="flex justify-between items-center py-4">
        <div class="flex items-center space-x-2">
          <div class="h-8 w-8 bg-primary rounded-md flex items-center justify-center">
            <i class="fa fa-leaf text-white"></i>
          </div>
          <div class="h-8 w-8 bg-secondary rounded-md flex items-center justify-center">
            <i class="fa fa-bolt text-white"></i>
          </div>
          <span class="text-xl font-bold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent">Vite
            + Vue3</span>
        </div>

        <!-- 桌面导航 -->
        <nav class="hidden md:flex space-x-8">
          <a href="#setup" class="text-gray-600 hover:text-primary transition-smooth font-medium">项目搭建</a>
          <a href="#structure" class="text-gray-600 hover:text-primary transition-smooth font-medium">项目结构</a>
          <a href="#modules" class="text-gray-600 hover:text-primary transition-smooth font-medium">模块化开发</a>
          <a href="#vue3-core" class="text-gray-600 hover:text-primary transition-smooth font-medium">Vue3核心</a>
        </nav>

        <!-- 移动端菜单按钮 -->
        <button id="menuBtn" class="md:hidden text-gray-600 hover:text-primary">
          <i class="fa fa-bars text-xl"></i>
        </button>
      </div>
    </div>

    <!-- 移动端导航菜单 -->
    <div id="mobileMenu" class="md:hidden hidden bg-white border-t">
      <div class="container mx-auto px-4 py-3 space-y-3">
        <a href="#setup" class="block text-gray-600 hover:text-primary transition-smooth font-medium py-2">项目搭建</a>
        <a href="#structure" class="block text-gray-600 hover:text-primary transition-smooth font-medium py-2">项目结构</a>
        <a href="#modules" class="block text-gray-600 hover:text-primary transition-smooth font-medium py-2">模块化开发</a>
        <a href="#vue3-core"
          class="block text-gray-600 hover:text-primary transition-smooth font-medium py-2">Vue3核心</a>
      </div>
    </div>
  </header>

  <!-- 英雄区域 -->
  <section class="pt-32 pb-20 bg-gradient-to-br from-gray-50 via-white to-gray-100">
    <div class="container mx-auto px-4 sm:px-6 lg:px-8">
      <div class="max-w-4xl mx-auto text-center">
        <h1 class="text-[clamp(2rem,5vw,3.5rem)] font-bold text-gray-900 leading-tight mb-6">
          Vite与Vue3核心指南
        </h1>
        <p class="text-[clamp(1.1rem,2vw,1.3rem)] text-gray-600 mb-10 leading-relaxed">
          从项目搭建到核心知识点，一站式掌握现代前端开发的强大工具组合
        </p>
        <div class="flex flex-col sm:flex-row justify-center gap-4">
          <a href="#setup"
            class="bg-primary hover:bg-primary/90 text-white font-medium py-3 px-8 rounded-lg transition-smooth shadow-lg hover:shadow-xl transform hover:-translate-y-1">
            开始学习 <i class="fa fa-arrow-right ml-2"></i>
          </a>
          <a href="#vue3-core"
            class="bg-white hover:bg-gray-50 text-gray-800 font-medium py-3 px-8 rounded-lg transition-smooth shadow-md hover:shadow-lg border border-gray-200 transform hover:-translate-y-1">
            Vue3核心 <i class="fa fa-code ml-2"></i>
          </a>
        </div>
      </div>
    </div>

    <!-- 装饰图形 -->
    <div class="absolute top-20 right-0 w-1/3 h-1/3 bg-secondary/5 rounded-full filter blur-3xl -z-10"></div>
    <div class="absolute bottom-10 left-0 w-1/4 h-1/4 bg-primary/5 rounded-full filter blur-3xl -z-10"></div>
  </section>

  <!-- 项目搭建部分 -->
  <section id="setup" class="py-20 bg-white">
    <div class="container mx-auto px-4 sm:px-6 lg:px-8">
      <div class="max-w-3xl mx-auto">
        <div class="text-center mb-16">
          <h2 class="text-[clamp(1.8rem,3vw,2.5rem)] font-bold text-gray-900 mb-4">项目搭建</h2>
          <p class="text-gray-600 text-lg">快速创建一个基于Vite和Vue3的现代前端项目</p>
        </div>

        <div class="bg-gray-50 rounded-xl shadow-sm p-6 mb-10 border border-gray-100">
          <h3 class="text-xl font-semibold mb-4 flex items-center">
            <span class="h-8 w-8 bg-secondary/10 text-secondary rounded-full flex items-center justify-center mr-3">
              <i class="fa fa-terminal"></i>
            </span>
            创建Vite项目
          </h3>

          <p class="text-gray-600 mb-4">使用npm创建一个新的Vite项目，按照提示选择Vue作为框架：</p>

          <div class="code-block">
            npm create vite@latest
          </div>

          <p class="text-gray-600 mb-4">按照终端提示完成项目名称和框架选择，然后进入项目目录并安装依赖：</p>

          <div class="code-block">
            cd 你的项目名称
            <br>
            npm install
          </div>
        </div>

        <div class="bg-gray-50 rounded-xl shadow-sm p-6 border border-gray-100">
          <h3 class="text-xl font-semibold mb-4 flex items-center">
            <span class="h-8 w-8 bg-secondary/10 text-secondary rounded-full flex items-center justify-center mr-3">
              <i class="fa fa-play"></i>
            </span>
            启动开发服务器
          </h3>

          <p class="text-gray-600 mb-4">安装依赖后，使用以下命令启动开发服务器：</p>

          <div class="code-block">
            npm run dev
          </div>

          <div class="bg-green-50 border border-green-100 rounded-lg p-4 mt-4">
            <div class="flex items-start">
              <i class="fa fa-info-circle text-green-500 mt-1 mr-3"></i>
              <p class="text-green-800 text-sm">启动成功后，你可以在浏览器中访问 <code
                  class="bg-white px-1 py-0.5 rounded text-green-700">http://localhost:5173</code>
                查看你的项目。Vite提供了极速的热模块替换(HMR)，修改代码后会实时更新。</p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </section>

  <!-- 项目结构部分 -->
  <section id="structure" class="py-20 bg-gray-50">
    <div class="container mx-auto px-4 sm:px-6 lg:px-8">
      <div class="max-w-3xl mx-auto">
        <div class="text-center mb-16">
          <h2 class="text-[clamp(1.8rem,3vw,2.5rem)] font-bold text-gray-900 mb-4">项目结构解读</h2>
          <p class="text-gray-600 text-lg">理解Vite + Vue3项目的目录结构和核心文件</p>
        </div>

        <!-- 目录结构可视化 -->
        <div class="bg-white rounded-xl shadow-md p-6 mb-12 border border-gray-100">
          <h3 class="text-xl font-semibold mb-6">目录结构</h3>

          <div class="space-y-3 text-gray-800">
            <div class="flex items-center">
              <i class="fa fa-folder text-yellow-500 mr-2"></i>
              <span class="font-medium">my-vite-project/</span>
            </div>

            <div class="ml-6 space-y-3">
              <div class="flex items-center">
                <i class="fa fa-folder text-yellow-500 mr-2"></i>
                <span>node_modules/</span>
                <span class="ml-2 text-xs text-gray-500">(项目依赖)</span>
              </div>

              <div class="flex items-center">
                <i class="fa fa-folder text-yellow-500 mr-2"></i>
                <span>public/</span>
                <span class="ml-2 text-xs text-gray-500">(静态资源)</span>
              </div>

              <div class="flex items-center">
                <i class="fa fa-folder text-yellow-500 mr-2"></i>
                <span class="font-medium">src/</span>
                <span class="ml-2 text-xs text-gray-500">(源代码)</span>
              </div>

              <div class="ml-6 space-y-3">
                <div class="flex items-center">
                  <i class="fa fa-folder text-yellow-500 mr-2"></i>
                  <span>assets/</span>
                  <span class="ml-2 text-xs text-gray-500">(资源文件)</span>
                </div>

                <div class="flex items-center">
                  <i class="fa fa-folder text-yellow-500 mr-2"></i>
                  <span>components/</span>
                  <span class="ml-2 text-xs text-gray-500">(组件)</span>
                </div>

                <div class="flex items-center">
                  <i class="fa fa-file-code-o text-blue-500 mr-2"></i>
                  <span>App.vue</span>
                  <span class="ml-2 text-xs text-gray-500">(根组件)</span>
                </div>

                <div class="flex items-center">
                  <i class="fa fa-file-code-o text-blue-500 mr-2"></i>
                  <span>main.js</span>
                  <span class="ml-2 text-xs text-gray-500">(入口文件)</span>
                </div>
              </div>

              <div class="flex items-center">
                <i class="fa fa-file-code-o text-blue-500 mr-2"></i>
                <span>index.html</span>
                <span class="ml-2 text-xs text-gray-500">(入口HTML)</span>
              </div>

              <div class="flex items-center">
                <i class="fa fa-file-code-o text-blue-500 mr-2"></i>
                <span>package.json</span>
                <span class="ml-2 text-xs text-gray-500">(项目配置)</span>
              </div>

              <div class="flex items-center">
                <i class="fa fa-file-code-o text-blue-500 mr-2"></i>
                <span>vite.config.js</span>
                <span class="ml-2 text-xs text-gray-500">(Vite配置)</span>
              </div>
            </div>
          </div>
        </div>

        <!-- 核心文件解析 -->
        <div class="space-y-10">
          <!-- index.html -->
          <div class="bg-white rounded-xl shadow-md overflow-hidden border border-gray-100">
            <div class="bg-gray-50 px-6 py-4 border-b border-gray-100">
              <h3 class="text-lg font-semibold flex items-center">
                <i class="fa fa-file-html-o text-orange-500 mr-2"></i>
                index.html
                <span class="ml-2 text-sm font-normal text-gray-500">项目入口文件</span>
              </h3>
            </div>
            <div class="p-6">
              <p class="text-gray-600 mb-4">Vite以HTML作为入口文件，直接在HTML中引入JavaScript入口文件：</p>

              <div class="code-block">
                &lt;!DOCTYPE html&gt;
                &lt;html lang="en"&gt;
                &lt;head&gt;
                &lt;meta charset="UTF-8" /&gt;
                &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
                &lt;title>Vite App&lt;/title&gt;
                &lt;/head&gt;
                &lt;body&gt;
                &lt;!-- 挂载点：Vue组件会渲染到这个div里 --&gt;
                &lt;div id="app"&gt;&lt;/div&gt;

                &lt;!-- 引入JS入口文件，type="module"是关键 --&gt;
                &lt;script type="module" src="/src/main.js"&gt;&lt;/script&gt;
                &lt;/body&gt;
                &lt;/html&gt;
              </div>

              <div class="mt-4 text-sm text-gray-600">
                <p class="font-medium mb-1">关键知识点：</p>
                <ul class="list-disc pl-5 space-y-1">
                  <li><code class="bg-gray-100 px-1 rounded">div#app</code> 是Vue应用的挂载点</li>
                  <li><code class="bg-gray-100 px-1 rounded">type="module"</code> 表示使用ES模块，是Vite快速开发的基础</li>
                </ul>
              </div>
            </div>
          </div>

          <!-- main.js -->
          <div class="bg-white rounded-xl shadow-md overflow-hidden border border-gray-100">
            <div class="bg-gray-50 px-6 py-4 border-b border-gray-100">
              <h3 class="text-lg font-semibold flex items-center">
                <i class="fa fa-file-code-o text-yellow-500 mr-2"></i>
                src/main.js
                <span class="ml-2 text-sm font-normal text-gray-500">JS入口文件</span>
              </h3>
            </div>
            <div class="p-6">
              <p class="text-gray-600 mb-4">JavaScript入口文件，负责创建Vue应用并挂载到页面：</p>

              <div class="code-block">
                // 导入Vue的核心功能
                import { createApp } from 'vue'

                // 导入根组件
                import App from './App.vue'

                // 导入全局样式
                import './index.css'

                // 创建应用并挂载到#app
                createApp(App).mount('#app')
              </div>

              <div class="mt-4 text-sm text-gray-600">
                <p class="font-medium mb-1">关键知识点：</p>
                <ul class="list-disc pl-5 space-y-1">
                  <li><code class="bg-gray-100 px-1 rounded">createApp(App)</code> 创建一个Vue应用实例</li>
                  <li><code class="bg-gray-100 px-1 rounded">mount('#app')</code> 将应用挂载到HTML中的#app元素</li>
                </ul>
              </div>
            </div>
          </div>

          <!-- App.vue -->
          <div class="bg-white rounded-xl shadow-md overflow-hidden border border-gray-100">
            <div class="bg-gray-50 px-6 py-4 border-b border-gray-100">
              <h3 class="text-lg font-semibold flex items-center">
                <i class="fa fa-file-code-o text-green-500 mr-2"></i>
                src/App.vue
                <span class="ml-2 text-sm font-normal text-gray-500">根组件</span>
              </h3>
            </div>
            <div class="p-6">
              <p class="text-gray-600 mb-4">Vue单文件组件，包含模板、脚本和样式：</p>

              <div class="code-block">
                &lt;template&gt;
                &lt;div class="app"&gt;
                &lt;HelloWorld msg="Vite + Vue" /&gt;
                &lt;/div&gt;
                &lt;/template&gt;

                &lt;script setup&gt;
                // 导入子组件
                import HelloWorld from './components/HelloWorld.vue'
                &lt;/script&gt;

                &lt;style scoped&gt;
                .app {
                text-align: center;
                padding: 2rem;
                }
                &lt;/style&gt;
              </div>

              <div class="mt-4 text-sm text-gray-600">
                <p class="font-medium mb-1">关键知识点：</p>
                <ul class="list-disc pl-5 space-y-1">
                  <li><code class="bg-gray-100 px-1 rounded">&lt;template&gt;</code> 包含组件的HTML结构</li>
                  <li><code class="bg-gray-100 px-1 rounded">&lt;script setup&gt;</code>
                    包含组件的JavaScript逻辑，setup是Vue3的语法糖</li>
                  <li><code class="bg-gray-100 px-1 rounded">&lt;style scoped&gt;</code> 包含组件的样式，scoped表示样式仅作用于当前组件</li>
                </ul>
              </div>
            </div>
          </div>

          <!-- vite.config.js -->
          <div class="bg-white rounded-xl shadow-md overflow-hidden border border-gray-100">
            <div class="bg-gray-50 px-6 py-4 border-b border-gray-100">
              <h3 class="text-lg font-semibold flex items-center">
                <i class="fa fa-file-code-o text-purple-500 mr-2"></i>
                vite.config.js
                <span class="ml-2 text-sm font-normal text-gray-500">Vite配置文件</span>
              </h3>
            </div>
            <div class="p-6">
              <p class="text-gray-600 mb-4">Vite的配置文件，用于配置服务器、插件等：</p>

              <div class="code-block">
                import { defineConfig } from 'vite'
                import vue from '@vitejs/plugin-vue'

                export default defineConfig({
                // 配置Vite插件
                plugins: [vue()],

                // 开发服务器配置
                server: {
                port: 3000, // 端口号
                open: true // 自动打开浏览器
                }
                })
              </div>

              <div class="mt-4 text-sm text-gray-600">
                <p class="font-medium mb-1">关键知识点：</p>
                <ul class="list-disc pl-5 space-y-1">
                  <li><code class="bg-gray-100 px-1 rounded">plugins: [vue()]</code> 配置Vue插件，让Vite支持Vue组件</li>
                  <li><code class="bg-gray-100 px-1 rounded">server</code> 配置开发服务器选项，如端口号、是否自动打开浏览器等</li>
                </ul>
              </div>
            </div>
          </div>

          <!-- package.json -->
          <div class="bg-white rounded-xl shadow-md overflow-hidden border border-gray-100">
            <div class="bg-gray-50 px-6 py-4 border-b border-gray-100">
              <h3 class="text-lg font-semibold flex items-center">
                <i class="fa fa-file-code-o text-red-500 mr-2"></i>
                package.json
                <span class="ml-2 text-sm font-normal text-gray-500">项目依赖配置</span>
              </h3>
            </div>
            <div class="p-6">
              <p class="text-gray-600 mb-4">项目的依赖配置文件，包含项目信息、依赖和脚本：</p>

              <div class="code-block">
                {
                "name": "my-vite-project",
                "private": true,
                "version": "0.1.0",
                "scripts": {
                "dev": "vite" // 启动开发服务器
                },
                "dependencies": {
                "vue": "^3.3.4" // 生产依赖
                },
                "devDependencies": {
                "@vitejs/plugin-vue": "^4.2.3",
                "vite": "^4.4.5" // 开发依赖
                }
                }
              </div>

              <div class="mt-4 text-sm text-gray-600">
                <p class="font-medium mb-1">关键知识点：</p>
                <ul class="list-disc pl-5 space-y-1">
                  <li><code class="bg-gray-100 px-1 rounded">scripts</code> 定义了常用的命令，使用<code
                      class="bg-gray-100 px-1 rounded">npm run 命令名</code>执行</li>
                  <li><code class="bg-gray-100 px-1 rounded">dependencies</code> 是项目运行时必需的依赖</li>
                  <li><code class="bg-gray-100 px-1 rounded">devDependencies</code> 是仅开发时需要的依赖</li>
                </ul>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </section>

  <!-- 模块化开发部分 -->
  <section id="modules" class="py-20 bg-white">
    <div class="container mx-auto px-4 sm:px-6 lg:px-8">
      <div class="max-w-3xl mx-auto">
        <div class="text-center mb-16">
          <h2 class="text-[clamp(1.8rem,3vw,2.5rem)] font-bold text-gray-900 mb-4">ES模块与工程化</h2>
          <p class="text-gray-600 text-lg">现代前端开发的模块化解决方案与工程化实践</p>
        </div>

        <!-- ES模块基础 -->
        <div class="mb-16">
          <h3 class="text-2xl font-semibold mb-6 pb-2 border-b border-gray-200 flex items-center">
            <span class="h-8 w-8 bg-secondary/10 text-secondary rounded-full flex items-center justify-center mr-3">
              <i class="fa fa-cubes"></i>
            </span>
            ES模块(ESM)基础
          </h3>

          <p class="text-gray-600 mb-6">ES模块是ECMAScript标准的模块化系统，允许将代码分割成独立的文件，通过导入导出机制实现代码复用。</p>

          <div class="grid md:grid-cols-2 gap-6 mb-8">
            <div>
              <h4 class="font-semibold text-lg mb-3 text-secondary">导出(Export)</h4>
              <p class="text-gray-600 text-sm mb-3">将模块中的变量、函数或类暴露给其他模块：</p>

              <div class="code-block text-xs">
                // utils.js
                // 命名导出 - 可以导出多个
                export const PI = 3.14159
                export function add(a, b) {
                return a + b
                }

                // 默认导出 - 每个模块只能有一个
                export default function multiply(a, b) {
                return a * b
                }
              </div>
            </div>

            <div>
              <h4 class="font-semibold text-lg mb-3 text-secondary">导入(Import)</h4>
              <p class="text-gray-600 text-sm mb-3">从其他模块引入内容：</p>

              <div class="code-block text-xs">
                // app.js
                // 导入命名导出的内容
                import { PI, add } from './utils.js'

                // 导入默认导出的内容
                import multiply from './utils.js'

                // 别名导入
                import { add as sum } from './utils.js'

                // 整体导入
                import * as Utils from './utils.js'

                console.log(PI) // 3.14159
                console.log(add(1, 2)) // 3
                console.log(multiply(2, 3)) // 6
              </div>
            </div>
          </div>

          <div class="bg-blue-50 border border-blue-100 rounded-lg p-4">
            <div class="flex items-start">
              <i class="fa fa-info-circle text-blue-500 mt-1 mr-3"></i>
              <p class="text-blue-800 text-sm">在浏览器中使用ES模块时，必须在script标签上添加<code
                  class="bg-white px-1 py-0.5 rounded text-blue-700">type="module"</code>属性。Vite基于原生ES模块实现，无需打包即可直接运行。
              </p>
            </div>
          </div>
        </div>

        <!-- 模块化工程化 -->
        <div class="mb-16">
          <h3 class="text-2xl font-semibold mb-6 pb-2 border-b border-gray-200 flex items-center">
            <span class="h-8 w-8 bg-secondary/10 text-secondary rounded-full flex items-center justify-center mr-3">
              <i class="fa fa-cogs"></i>
            </span>
            前端工程化与模块化
          </h3>

          <p class="text-gray-600 mb-6">现代前端工程化通过工具链解决模块化开发中的各种问题，提供更高效的开发体验：</p>

          <div class="grid md:grid-cols-3 gap-4 mb-8">
            <div class="bg-gray-50 p-5 rounded-lg border border-gray-100">
              <div class="h-10 w-10 bg-secondary/10 text-secondary rounded-full flex items-center justify-center mb-3">
                <i class="fa fa-code-fork"></i>
              </div>
              <h4 class="font-semibold mb-2">模块打包</h4>
              <p class="text-sm text-gray-600">将多个模块打包成少量文件，优化加载性能，处理模块依赖关系</p>
            </div>

            <div class="bg-gray-50 p-5 rounded-lg border border-gray-100">
              <div class="h-10 w-10 bg-secondary/10 text-secondary rounded-full flex items-center justify-center mb-3">
                <i class="fa fa-refresh"></i>
              </div>
              <h4 class="font-semibold mb-2">热模块替换</h4>
              <p class="text-sm text-gray-600">修改代码后无需刷新页面即可看到效果，保持应用状态</p>
            </div>

            <div class="bg-gray-50 p-5 rounded-lg border border-gray-100">
              <div class="h-10 w-10 bg-secondary/10 text-secondary rounded-full flex items-center justify-center mb-3">
                <i class="fa fa-compress"></i>
              </div>
              <h4 class="font-semibold mb-2">代码优化</h4>
              <p class="text-sm text-gray-600">压缩、Tree-shaking、代码分割等优化，减小文件体积</p>
            </div>
          </div>

          <h4 class="font-semibold text-lg mb-4">Vite的模块化处理</h4>
          <p class="text-gray-600 mb-4">Vite在开发环境中使用原生ES模块，避免了传统打包工具的性能问题：</p>

          <div class="code-block mb-6">
            // 开发环境：原生ES模块直接运行
            // 无需打包，启动速度极快
            import { createApp } from 'vue'
            import App from './App.vue'

            // 生产环境：高效打包优化
            // 自动进行代码分割、压缩等处理
          </div>

          <div class="bg-green-50 border border-green-100 rounded-lg p-4">
            <div class="flex items-start">
              <i class="fa fa-lightbulb-o text-green-500 mt-1 mr-3"></i>
              <p class="text-green-800 text-sm">Vite采用"按需编译"策略，只编译当前需要的模块，大幅提升开发效率。生产环境则使用Rollup进行高效打包，兼顾开发体验和生产性能。</p>
            </div>
          </div>
        </div>

        <!-- 模块化最佳实践 -->
        <div>
          <h3 class="text-2xl font-semibold mb-6 pb-2 border-b border-gray-200 flex items-center">
            <span class="h-8 w-8 bg-secondary/10 text-secondary rounded-full flex items-center justify-center mr-3">
              <i class="fa fa-check-circle"></i>
            </span>
            模块化最佳实践
          </h3>

          <div class="space-y-4 mb-6">
            <div class="bg-gray-50 p-4 rounded-lg border border-gray-100">
              <h4 class="font-medium mb-2">单一职责原则</h4>
              <p class="text-sm text-gray-600">一个模块只负责一个功能，保持模块的简洁和可维护性</p>
            </div>

            <div class="bg-gray-50 p-4 rounded-lg border border-gray-100">
              <h4 class="font-medium mb-2">明确的导入导出</h4>
              <p class="text-sm text-gray-600">只导出必要的内容，避免导出过多造成依赖混乱；导入时明确指定需要的内容</p>
            </div>

            <div class="bg-gray-50 p-4 rounded-lg border border-gray-100">
              <h4 class="font-medium mb-2">合理的目录结构</h4>
              <p class="text-sm text-gray-600">按功能或业务划分模块目录，如utils、components、views等，便于查找和管理</p>
            </div>

            <div class="bg-gray-50 p-4 rounded-lg border border-gray-100">
              <h4 class="font-medium mb-2">避免循环依赖</h4>
              <p class="text-sm text-gray-600">设计模块时避免A依赖B，B又依赖A的情况，可能导致不可预期的问题</p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </section>

  <!-- Vue3核心知识点部分 -->
  <section id="vue3-core" class="py-20 bg-gray-50">
    <div class="container mx-auto px-4 sm:px-6 lg:px-8">
      <div class="max-w-3xl mx-auto">
        <div class="text-center mb-16">
          <h2 class="text-[clamp(1.8rem,3vw,2.5rem)] font-bold text-gray-900 mb-4">Vue3核心知识点</h2>
          <p class="text-gray-600 text-lg">掌握Vue3开发中最常用的核心概念和语法</p>
        </div>

        <!-- 组件基础 -->
        <div class="mb-16">
          <h3 class="text-2xl font-semibold mb-6 pb-2 border-b border-gray-200 flex items-center">
            <span class="h-8 w-8 bg-primary/10 text-primary rounded-full flex items-center justify-center mr-3">
              <i class="fa fa-cubes"></i>
            </span>
            组件基础
          </h3>

          <p class="text-gray-600 mb-6">Vue3的组件是单文件组件(SFC)，扩展名为.vue，每个组件包含三个部分：</p>

          <div class="bg-gray-50 rounded-lg p-4 mb-6">
            <div class="flex items-center text-gray-700 mb-2">
              <i class="fa fa-html5 text-orange-500 mr-2"></i>
              <span class="font-medium">&lt;template&gt;</span>
              <span class="ml-2 text-sm text-gray-500">组件的HTML结构</span>
            </div>
            <div class="flex items-center text-gray-700 mb-2">
              <i class="fa fa-code text-yellow-500 mr-2"></i>
              <span class="font-medium">&lt;script setup&gt;</span>
              <span class="ml-2 text-sm text-gray-500">组件的JavaScript逻辑</span>
            </div>
            <div class="flex items-center text-gray-700">
              <i class="fa fa-css3 text-blue-500 mr-2"></i>
              <span class="font-medium">&lt;style scoped&gt;</span>
              <span class="ml-2 text-sm text-gray-500">组件的样式，scoped表示样式隔离</span>
            </div>
          </div>

          <div class="code-block">
            &lt;template&gt;
            &lt;div class="greeting"&gt;
            {{ message }}
            &lt;/div&gt;
            &lt;/template&gt;

            &lt;script setup&gt;
            // 定义响应式数据
            const message = "Hello Vue3"
            &lt;/script&gt;

            &lt;style scoped&gt;
            .greeting {
            color: #42b983;
            font-size: 1.2rem;
            }
            &lt;/style&gt;
          </div>
        </div>

        <!-- 响应式数据 -->
        <div class="mb-16">
          <h3 class="text-2xl font-semibold mb-6 pb-2 border-b border-gray-200 flex items-center">
            <span class="h-8 w-8 bg-primary/10 text-primary rounded-full flex items-center justify-center mr-3">
              <i class="fa fa-refresh"></i>
            </span>
            响应式数据
          </h3>

          <p class="text-gray-600 mb-6">Vue3提供了多种定义响应式数据的方式，核心是基于Proxy实现的响应式系统：</p>

          <div class="grid md:grid-cols-2 gap-6 mb-6">
            <div class="bg-gray-50 rounded-xl p-5 border border-gray-100">
              <h4 class="font-semibold text-lg mb-3 text-primary">ref</h4>
              <p class="text-gray-600 text-sm mb-3">用于基本类型（数字、字符串、布尔）和单值对象，访问时需要使用.value</p>

              <div class="code-block text-xs">
                import { ref } from 'vue'

                // 定义响应式数据
                const count = ref(0)
                const message = ref("Hello")
                const user = ref({ name: "张三" })

                // 读取数据（脚本中需要 .value）
                console.log(count.value) // 0
                console.log(user.value.name) // "张三"

                // 修改数据（必须用 .value）
                const increment = () => {
                count.value++
                user.value.name = "李四"
                }
              </div>
            </div>

            <div class="bg-gray-50 rounded-xl p-5 border border-gray-100">
              <h4 class="font-semibold text-lg mb-3 text-primary">reactive</h4>
              <p class="text-gray-600 text-sm mb-3">用于复杂对象（对象、数组），直接修改属性即可，不需要.value</p>

              <div class="code-block text-xs">
                import { reactive } from 'vue'

                // 定义响应式对象
                const user = reactive({
                name: "张三",
                age: 20,
                address: {
                city: "北京"
                }
                })

                // 读取数据
                console.log(user.name) // "张三"

                // 修改数据
                const changeName = () => {
                user.name = "李四"
                user.age++
                user.address.city = "上海"
                }
              </div>
            </div>
          </div>

          <div class="grid md:grid-cols-2 gap-6">
            <div class="bg-gray-50 rounded-xl p-5 border border-gray-100">
              <h4 class="font-semibold text-lg mb-3 text-primary">toRef</h4>
              <p class="text-gray-600 text-sm mb-3">将响应式对象的属性转为ref，保持响应式关联</p>

              <div class="code-block text-xs">
                import { reactive, toRef } from 'vue'

                const user = reactive({
                name: "张三",
                age: 20
                })

                // 将属性转为ref
                const nameRef = toRef(user, 'name')

                // 修改ref会影响原对象
                nameRef.value = "李四"
                console.log(user.name) // "李四"
              </div>
            </div>

            <div class="bg-gray-50 rounded-xl p-5 border border-gray-100">
              <h4 class="font-semibold text-lg mb-3 text-primary">toRefs</h4>
              <p class="text-gray-600 text-sm mb-3">将响应式对象的所有属性转为ref，返回一个包含这些ref的普通对象</p>

              <div class="code-block text-xs">
                import { reactive, toRefs } from 'vue'

                const user = reactive({
                name: "张三",
                age: 20
                })

                // 将所有属性转为ref
                const { name, age } = toRefs(user)

                // 可以直接使用解构后的ref
                console.log(name.value) // "张三"
                age.value++
                console.log(user.age) // 21
              </div>
            </div>
          </div>

          <div class="bg-blue-50 border border-blue-100 rounded-lg p-4 mt-6">
            <div class="flex items-start">
              <i class="fa fa-lightbulb-o text-blue-500 mt-1 mr-3"></i>
              <p class="text-blue-800 text-sm">实际开发中，<code class="bg-white px-1 py-0.5 rounded text-blue-700">ref</code>
                更为常用，因为它可以用于任何类型的数据，包括对象和数组。当ref存储对象时，Vue会自动将其转换为reactive代理。</p>
            </div>
          </div>
        </div>

        <!-- 组件通信 -->
        <div class="mb-16">
          <h3 class="text-2xl font-semibold mb-6 pb-2 border-b border-gray-200 flex items-center">
            <span class="h-8 w-8 bg-primary/10 text-primary rounded-full flex items-center justify-center mr-3">
              <i class="fa fa-exchange"></i>
            </span>
            组件通信
          </h3>

          <p class="text-gray-600 mb-6">组件之间的数据传递是Vue开发的核心，根据组件关系不同，有多种通信方式：</p>

          <div class="mb-8">
            <h4 class="font-semibold text-lg mb-4 text-gray-800">父传子（props）</h4>

            <div class="grid md:grid-cols-2 gap-6">
              <div>
                <p class="text-gray-600 text-sm mb-3">父组件通过属性传递数据：</p>
                <div class="code-block text-xs">
                  &lt;template&gt;
                  &lt;!-- 父组件传递数据给子组件 --&gt;
                  &lt;ChildComponent
                  title="来自父组件的数据"
                  :count="10"
                  :isActive="true"
                  /&gt;
                  &lt;/template&gt;

                  &lt;script setup&gt;
                  import ChildComponent from './ChildComponent.vue'
                  &lt;/script&gt;
                </div>
              </div>

              <div>
                <p class="text-gray-600 text-sm mb-3">子组件通过defineProps接收：</p>
                <div class="code-block text-xs">
                  &lt;template&gt;
                  &lt;h2&gt;{{ title }}&lt;/h2&gt;
                  &lt;p&gt;数量: {{ count }}&lt;/p&gt;
                  &lt;p&gt;状态: {{ isActive ? '激活' : '未激活' }}&lt;/p&gt;
                  &lt;/template&gt;

                  &lt;script setup&gt;
                  // 定义接收的参数及其类型
                  const props = defineProps({
                  title: {
                  type: String,
                  required: true // 必须传
                  },
                  count: {
                  type: Number,
                  default: 0 // 默认值
                  },
                  isActive: Boolean
                  })

                  // 在脚本中访问props
                  console.log(props.title)
                  </script&gt; </div>
                </div>
              </div>
            </div>

            <div class="mb-8">
              <h4 class="font-semibold text-lg mb-4 text-gray-800">子传父（emit）</h4>

              <div class="grid md:grid-cols-2 gap-6">
                <div>
                  <p class="text-gray-600 text-sm mb-3">子组件通过emit触发事件传递数据：</p>
                  <div class="code-block text-xs">
                    &lt;template&gt;
                    &lt;button @click="sendData"&gt;点击传值&lt;/button&gt;
                    &lt;input
                    type="text"
                    :value="inputValue"
                    @input="handleInput"
                    &gt;
                    &lt;/template&gt;

                    &lt;script setup&gt;
                    import { ref } from 'vue'

                    // 定义可触发的事件
                    const emit = defineEmits(['send', 'input-change'])
                    const inputValue = ref('')

                    const sendData = () => {
                    // 触发事件并传值
                    emit('send', '来自子组件的数据')
                    }

                    const handleInput = (e) => {
                    inputValue.value = e.target.value
                    emit('input-change', inputValue.value)
                    }
                    &lt;/script&gt;
                  </div>
                </div>

                <div>
                  <p class="text-gray-600 text-sm mb-3">父组件监听事件接收数据：</p>
                  <div class="code-block text-xs">
                    &lt;template&gt;
                    &lt;ChildComponent
                    @send="handleReceive"
                    @input-change="handleInputChange"
                    /&gt;
                    &lt;p&gt;收到的消息: {{ message }}&lt;/p&gt;
                    &lt;p&gt;输入的内容: {{ inputText }}&lt;/p&gt;
                    &lt;/template&gt;

                    &lt;script setup&gt;
                    import { ref } from 'vue'
                    import ChildComponent from './ChildComponent.vue'

                    const message = ref('')
                    const inputText = ref('')

                    const handleReceive = (data) => {
                    message.value = data
                    }

                    const handleInputChange = (text) => {
                    inputText.value = text
                    }
                    &lt;/script&gt;
                  </div>
                </div>
              </div>
            </div>

            <div>
              <h4 class="font-semibold text-lg mb-4 text-gray-800">其他通信方式</h4>

              <div class="grid md:grid-cols-2 gap-6">
                <div class="bg-gray-50 p-5 rounded-lg border border-gray-100">
                  <h5 class="font-medium mb-2">provide / inject</h5>
                  <p class="text-sm text-gray-600 mb-3">用于深层嵌套组件通信，父组件提供数据，后代组件注入数据</p>

                  <div class="code-block text-xs">
                    // 父组件提供数据
                    import { provide } from 'vue'
                    provide('theme', 'dark')

                    // 后代组件注入数据
                    import { inject } from 'vue'
                    const theme = inject('theme', 'light') // 第二个参数是默认值
                  </div>
                </div>

                <div class="bg-gray-50 p-5 rounded-lg border border-gray-100">
                  <h5 class="font-medium mb-2">Pinia状态管理</h5>
                  <p class="text-sm text-gray-600 mb-3">用于跨组件、跨页面共享状态，适合中大型应用</p>

                  <div class="code-block text-xs">
                    // store.js
                    import { defineStore } from 'pinia'
                    export const useCounterStore = defineStore('counter', {
                    state: () => ({ count: 0 }),
                    actions: {
                    increment() { this.count++ }
                    }
                    })

                    // 任何组件中使用
                    import { useCounterStore } from './store'
                    const store = useCounterStore()
                    console.log(store.count) // 0
                    store.increment()
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- 模板语法 -->
          <div class="mb-16">
            <h3 class="text-2xl font-semibold mb-6 pb-2 border-b border-gray-200 flex items-center">
              <span class="h-8 w-8 bg-primary/10 text-primary rounded-full flex items-center justify-center mr-3">
                <i class="fa fa-html5"></i>
              </span>
              模板语法
            </h3>

            <div class="space-y-6">
              <div>
                <h4 class="font-semibold mb-3">插值表达式</h4>
                <p class="text-gray-600 text-sm mb-3">用双大括号{{ }}显示数据：</p>
                <div class="code-block">
                  &lt;template&gt;
                  &lt;div&gt;{{ message }}&lt;/div&gt; <!-- 显示变量 -->
                  &lt;div&gt;{{ 1 + 1 }}&lt;/div&gt; <!-- 支持简单计算 -->
                  &lt;div&gt;{{ user.name.toUpperCase() }}&lt;/div&gt; <!-- 支持方法调用 -->
                  &lt;div v-text="message"&gt;&lt;/div&gt; <!-- 与{{}}等效 -->
                  &lt;div v-html="rawHtml"&gt;&lt;/div&gt; <!-- 渲染HTML -->
                  &lt;/template&gt;
                </div>
              </div>

              <div>
                <h4 class="font-semibold mb-3">常用指令</h4>

                <div class="grid md:grid-cols-2 gap-4">
                  <div class="bg-gray-50 p-4 rounded-lg border border-gray-100">
                    <p class="font-medium mb-2">v-bind（简写:）</p>
                    <p class="text-sm text-gray-600 mb-2">绑定属性：</p>
                    <div class="code-block text-xs">
                      &lt;img :src="imageUrl" :alt="imageAlt"&gt;
                      &lt;div :class="{ active: isActive }"&gt;&lt;/div&gt;
                      &lt;div :style="{ color: textColor, fontSize: '16px' }"&gt;&lt;/div&gt;
                    </div>
                  </div>

                  <div class="bg-gray-50 p-4 rounded-lg border border-gray-100">
                    <p class="font-medium mb-2">v-on（简写@）</p>
                    <p class="text-sm text-gray-600 mb-2">绑定事件：</p>
                    <div class="code-block text-xs">
                      &lt;button @click="handleClick"&gt;点击&lt;/button&gt;
                      &lt;button @click="handleAdd(10, $event)"&gt;传参&lt;/button&gt;
                      &lt;input @input="handleInput"&gt;
                      &lt;form @submit.prevent="handleSubmit"&gt;&lt;/form&gt; <!-- 事件修饰符 -->
                    </div>
                  </div>

                  <div class="bg-gray-50 p-4 rounded-lg border border-gray-100">
                    <p class="font-medium mb-2">v-if / v-else</p>
                    <p class="text-sm text-gray-600 mb-2">条件渲染：</p>
                    <div class="code-block text-xs">
                      &lt;div v-if="isShow"&gt;显示&lt;/div&gt;
                      &lt;div v-else-if="isLoading"&gt;加载中&lt;/div&gt;
                      &lt;div v-else&gt;隐藏&lt;/div&gt;

                      &lt;!-- template分组 --&gt;
                      &lt;template v-if="hasItems"&gt;
                      &lt;h2&gt;列表&lt;/h2&gt;
                      &lt;ul&gt;...&lt;/ul&gt;
                      &lt;/template&gt;
                    </div>
                  </div>

                  <div class="bg-gray-50 p-4 rounded-lg border border-gray-100">
                    <p class="font-medium mb-2">v-for</p>
                    <p class="text-sm text-gray-600 mb-2">列表渲染：</p>
                    <div class="code-block text-xs">
                      &lt;!-- 遍历数组 --&gt;
                      &lt;ul&gt;
                      &lt;li v-for="(item, index) in list" :key="item.id"&gt;
                      {{ index }}: {{ item.name }}
                      &lt;/li&gt;
                      &lt;/ul&gt;

                      &lt;!-- 遍历对象 --&gt;
                      &lt;div v-for="(value, key) in user" :key="key"&gt;
                      {{ key }}: {{ value }}
                      &lt;/div&gt;
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- v-model -->
          <div class="mb-16">
            <h3 class="text-2xl font-semibold mb-6 pb-2 border-b border-gray-200 flex items-center">
              <span class="h-8 w-8 bg-primary/10 text-primary rounded-full flex items-center justify-center mr-3">
                <i class="fa fa-exchange"></i>
              </span>
              v-model双向绑定
            </h3>

            <p class="text-gray-600 mb-6">v-model用于表单输入与数据的双向绑定，数据变化时视图自动更新，视图变化时数据也自动更新。</p>

            <div class="code-block mb-6">
              &lt;template&gt;
              &lt;!-- 文本输入框 --&gt;
              &lt;input type="text" v-model="username"&gt;
              &lt;p&gt;你输入的用户名：{{ username }}&lt;/p&gt;

              &lt;!-- 复选框（单个） --&gt;
              &lt;input type="checkbox" v-model="isAgree"&gt;
              &lt;p&gt;是否同意：{{ isAgree ? '是' : '否' }}&lt;/p&gt;

              &lt;!-- 复选框（多个） --&gt;
              &lt;div&gt;
              &lt;input type="checkbox" value="apple" v-model="fruits"&gt;苹果
              &lt;input type="checkbox" value="banana" v-model="fruits"&gt;香蕉
              &lt;p&gt;选中的水果：{{ fruits.join(',') }}&lt;/p&gt;
              &lt;/div&gt;

              &lt;!-- 单选框（一组） --&gt;
              &lt;div&gt;
              &lt;input type="radio" value="男" v-model="gender"&gt;男
              &lt;input type="radio" value="女" v-model="gender"&gt;女
              &lt;p&gt;选中的性别：{{ gender }}&lt;/p&gt;
              &lt;/div&gt;

              &lt;!-- 下拉框 --&gt;
              &lt;select v-model="selectedCity"&gt;
              &lt;option value="beijing"&gt;北京&lt;/option&gt;
              &lt;option value="shanghai"&gt;上海&lt;/option&gt;
              &lt;/select&gt;
              &lt;p&gt;选中的城市：{{ selectedCity }}&lt;/p&gt;
              &lt;/template&gt;

              &lt;script setup&gt;
              import { ref } from 'vue'

              const username = ref('')
              const isAgree = ref(false)
              const fruits = ref([])
              const gender = ref('')
              const selectedCity = ref('beijing')
              &lt;/script&gt;
            </div>

            <h4 class="font-semibold mb-3">v-model修饰符</h4>
            <div class="grid md:grid-cols-3 gap-4 mb-6">
              <div class="bg-gray-50 p-4 rounded-lg border border-gray-100">
                <p class="font-medium mb-2">.trim</p>
                <p class="text-sm text-gray-600">自动去除首尾空格：</p>
                <div class="code-block text-xs">
                  &lt;input v-model.trim="username"&gt;
                </div>
              </div>

              <div class="bg-gray-50 p-4 rounded-lg border border-gray-100">
                <p class="font-medium mb-2">.number</p>
                <p class="text-sm text-gray-600">自动转为数字：</p>
                <div class="code-block text-xs">
                  &lt;input v-model.number="age"&gt;
                </div>
              </div>

              <div class="bg-gray-50 p-4 rounded-lg border border-gray-100">
                <p class="font-medium mb-2">.lazy</p>
                <p class="text-sm text-gray-600">失焦时才同步：</p>
                <div class="code-block text-xs">
                  &lt;input v-model.lazy="search"&gt;
                </div>
              </div>
            </div>

            <div class="bg-gray-50 p-5 rounded-lg border border-gray-100">
              <h4 class="font-medium mb-3">自定义组件使用v-model</h4>
              <p class="text-sm text-gray-600 mb-3">通过modelValue属性和update:modelValue事件实现：</p>

              <div class="code-block text-xs">
                &lt;!-- 子组件 MyInput.vue --&gt;
                &lt;template&gt;
                &lt;input
                :value="modelValue"
                @input="$emit('update:modelValue', $event.target.value)"
                &gt;
                &lt;/template&gt;

                &lt;script setup&gt;
                defineProps(['modelValue'])
                defineEmits(['update:modelValue'])
                &lt;/script&gt;

                &lt;!-- 父组件中使用 --&gt;
                &lt;template&gt;
                &lt;MyInput v-model="username" /&gt;
                &lt;/template&gt;
              </div>
            </div>
          </div>

          <!-- 生命周期 -->
          <div class="mb-16">
            <h3 class="text-2xl font-semibold mb-6 pb-2 border-b border-gray-200 flex items-center">
              <span class="h-8 w-8 bg-primary/10 text-primary rounded-full flex items-center justify-center mr-3">
                <i class="fa fa-clock-o"></i>
              </span>
              生命周期钩子
            </h3>

            <p class="text-gray-600 mb-6">组件从创建到销毁的过程，常用的生命周期钩子：</p>

            <div class="code-block mb-6">
              &lt;script setup&gt;
              import {
              onBeforeMount,
              onMounted,
              onBeforeUpdate,
              onUpdated,
              onBeforeUnmount,
              onUnmounted
              } from 'vue'

              // 组件挂载前执行
              onBeforeMount(() => {
              console.log('组件即将挂载')
              })

              // 组件挂载到页面后执行
              onMounted(() => {
              console.log('组件已显示在页面上')
              // 初始化操作：请求数据、绑定事件
              })

              // 组件更新前执行
              onBeforeUpdate(() => {
              console.log('组件即将更新')
              })

              // 组件数据更新后执行
              onUpdated(() => {
              console.log('组件数据更新，DOM已更新')
              })

              // 组件销毁前执行
              onBeforeUnmount(() => {
              console.log('组件即将销毁')
              })

              // 组件销毁后执行
              onUnmounted(() => {
              console.log('组件已销毁')
              // 清理操作：解绑事件、清除定时器
              })
              &lt;/script&gt;
            </div>

            <div class="relative py-6">
              <div class="absolute inset-0 flex items-center">
                <div class="w-full border-t border-gray-200"></div>
              </div>
              <div class="relative flex justify-center text-sm">
                <span class="px-2 bg-gray-50 text-gray-500">生命周期流程</span>
              </div>
            </div>

            <div class="flex flex-wrap justify-between items-center text-sm text-gray-600">
              <div class="flex flex-col items-center mb-4">
                <div class="h-10 w-10 rounded-full bg-gray-100 flex items-center justify-center mb-2">
                  <i class="fa fa-cog text-gray-500"></i>
                </div>
                <span>setup</span>
              </div>

              <div class="h-1 flex-1 max-w-[30px] bg-gray-200 my-4"></div>

              <div class="flex flex-col items-center mb-4">
                <div class="h-10 w-10 rounded-full bg-gray-100 flex items-center justify-center mb-2">
                  <i class="fa fa-arrow-down text-gray-500"></i>
                </div>
                <span>onBeforeMount</span>
              </div>

              <div class="h-1 flex-1 max-w-[30px] bg-gray-200 my-4"></div>

              <div class="flex flex-col items-center mb-4">
                <div class="h-10 w-10 rounded-full bg-gray-100 flex items-center justify-center mb-2">
                  <i class="fa fa-plus text-gray-500"></i>
                </div>
                <span>onMounted</span>
              </div>

              <div class="h-1 flex-1 max-w-[30px] bg-gray-200 my-4"></div>

              <div class="flex flex-col items-center mb-4">
                <div class="h-10 w-10 rounded-full bg-gray-100 flex items-center justify-center mb-2">
                  <i class="fa fa-refresh text-gray-500"></i>
                </div>
                <span>onUpdated</span>
              </div>

              <div class="h-1 flex-1 max-w-[30px] bg-gray-200 my-4"></div>

              <div class="flex flex-col items-center mb-4">
                <div class="h-10 w-10 rounded-full bg-gray-100 flex items-center justify-center mb-2">
                  <i class="fa fa-minus text-gray-500"></i>
                </div>
                <span>onUnmounted</span>
              </div>
            </div>
          </div>

          <!-- 计算属性和侦听器 -->
          <div class="mb-16">
            <h3 class="text-2xl font-semibold mb-6 pb-2 border-b border-gray-200 flex items-center">
              <span class="h-8 w-8 bg-primary/10 text-primary rounded-full flex items-center justify-center mr-3">
                <i class="fa fa-calculator"></i>
              </span>
              计算属性和侦听器
            </h3>

            <div class="grid md:grid-cols-2 gap-8">
              <div>
                <h4 class="font-semibold text-lg mb-4 text-gray-800">计算属性 (computed)</h4>
                <p class="text-gray-600 mb-4">用于处理依赖其他数据计算得出的结果，会缓存结果：</p>

                <div class="code-block">
                  &lt;template&gt;
                  &lt;div&gt;原始价格：{{ price }}&lt;/div&gt;
                  &lt;div&gt;折扣后价格：{{ discountedPrice }}&lt;/div&gt;
                  &lt;div&gt;数量：&lt;input v-model.number="quantity"&gt;&lt;/div&gt;
                  &lt;div&gt;总价：{{ totalPrice }}&lt;/div&gt;
                  &lt;/template&gt;

                  &lt;script setup&gt;
                  import { ref, computed } from 'vue'

                  const price = ref(100)
                  const discount = ref(0.8)
                  const quantity = ref(1)

                  // 只读计算属性
                  const discountedPrice = computed(() => {
                  return price.value * discount.value
                  })

                  // 可写计算属性
                  const totalPrice = computed({
                  get() {
                  return discountedPrice.value * quantity.value
                  },
                  set(value) {
                  // 当直接修改totalPrice时触发
                  quantity.value = value / discountedPrice.value
                  }
                  })
                  &lt;/script&gt;
                </div>
              </div>

              <div>
                <h4 class="font-semibold text-lg mb-4 text-gray-800">侦听器 (watch)</h4>
                <p class="text-gray-600 mb-4">用于监听数据变化并执行副作用：</p>

                <div class="code-block">
                  &lt;template&gt;
                  &lt;div&gt;
                  &lt;input v-model="username"&gt;
                  &lt;div v-if="errorMessage" class="text-red-500"&gt;{{ errorMessage }}&lt;/div&gt;
                  &lt;/div&gt;
                  &lt;/template&gt;

                  &lt;script setup&gt;
                  import { ref, watch } from 'vue'

                  const username = ref('')
                  const errorMessage = ref('')

                  // 监听单个数据
                  watch(username, (newVal, oldVal) => {
                  if (newVal.length < 3) { errorMessage.value='用户名至少3个字符' } else { errorMessage.value='' } }) // 监听多个数据
                    const password=ref('') watch([username, password], ([newUser, newPwd], [oldUser, oldPwd])=> {
                    console.log('用户名或密码变化了')
                    })

                    // 监听对象属性
                    const user = ref({ name: '张三', age: 20 })
                    watch(
                    () => user.value.age,
                    (newAge) => {
                    console.log('年龄变化为：', newAge)
                    }
                    )

                    // 立即执行的watch
                    watch(username, (newVal) => {
                    // 组件创建时立即执行一次
                    }, { immediate: true })
                    &lt;/script&gt;
                </div>
              </div>
            </div>

            <div class="bg-blue-50 border border-blue-100 rounded-lg p-4 mt-6">
              <div class="flex items-start">
                <i class="fa fa-lightbulb-o text-blue-500 mt-1 mr-3"></i>
                <p class="text-blue-800 text-sm">
                  计算属性适合用于根据其他数据派生新数据的场景，而侦听器适合处理异步操作或复杂的副作用。计算属性会缓存结果，只有依赖变化时才会重新计算，而侦听器每次监听的数据变化都会执行。</p>
              </div>
            </div>
          </div>

          <!-- Composition API 与 Script Setup -->
          <div>
            <h3 class="text-2xl font-semibold mb-6 pb-2 border-b border-gray-200 flex items-center">
              <span class="h-8 w-8 bg-primary/10 text-primary rounded-full flex items-center justify-center mr-3">
                <i class="fa fa-code"></i>
              </span>
              Composition API 与 Script Setup
            </h3>

            <p class="text-gray-600 mb-6">Vue3引入的Composition API提供了更灵活的代码组织方式，而&lt;script setup&gt;是其语法糖，简化了使用：</p>

            <div class="grid md:grid-cols-2 gap-6 mb-8">
              <div class="bg-gray-50 p-5 rounded-lg border border-gray-100">
                <h4 class="font-semibold mb-3">代码组织优势</h4>
                <p class="text-sm text-gray-600 mb-3">按功能组织代码，而非选项（data、methods等）：</p>

                <div class="code-block text-xs">
                  &lt;script setup&gt;
                  import { ref, computed, watch } from 'vue'

                  // 用户相关功能
                  const username = ref('')
                  const validateUsername = () => { /* ... */ }

                  // 订单相关功能
                  const orderList = ref([])
                  const fetchOrders = async () => { /* ... */ }
                  const totalAmount = computed(() => { /* ... */ })

                  // 初始化
                  fetchOrders()
                  &lt;/script&gt;
                </div>
              </div>

              <div class="bg-gray-50 p-5 rounded-lg border border-gray-100">
                <h4 class="font-semibold mb-3">复用逻辑</h4>
                <p class="text-sm text-gray-600 mb-3">通过组合函数（Composables）复用逻辑：</p>

                <div class="code-block text-xs">
                  // composables/useCounter.js
                  import { ref, computed } from 'vue'
                  export function useCounter(initialValue = 0) {
                  const count = ref(initialValue)
                  const increment = () => count.value++
                  const decrement = () => count.value--
                  const double = computed(() => count.value * 2)

                  return { count, increment, decrement, double }
                  }

                  // 组件中使用
                  import { useCounter } from './composables/useCounter'
                  const { count, increment, double } = useCounter(10)
                </div>
              </div>
            </div>

            <div class="bg-gray-50 p-5 rounded-lg border border-gray-100">
              <h4 class="font-semibold mb-3">Script Setup 特性</h4>
              <div class="grid md:grid-cols-2 gap-4">
                <div>
                  <p class="text-sm font-medium mb-2">简化的导入导出</p>
                  <p class="text-xs text-gray-600">变量和函数自动暴露给模板，无需return</p>
                </div>

                <div>
                  <p class="text-sm font-medium mb-2">组件自动注册</p>
                  <p class="text-xs text-gray-600">导入的组件可直接在模板中使用，无需注册</p>
                </div>

                <div>
                  <p class="text-sm font-medium mb-2">props和emits</p>
                  <p class="text-xs text-gray-600">使用defineProps和defineEmits定义，无需导入</p>
                </div>

                <div>
                  <p class="text-sm font-medium mb-2">顶层await</p>
                  <p class="text-xs text-gray-600">支持直接在脚本中使用await，无需异步函数包裹</p>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
  </section>

  <!-- 页脚 -->
  <footer class="bg-gray-900 text-gray-300 py-12">
    <div class="container mx-auto px-4 sm:px-6 lg:px-8">
      <div class="max-w-3xl mx-auto text-center">
        <div class="flex items-center justify-center space-x-2 mb-6">
          <div class="h-8 w-8 bg-primary rounded-md flex items-center justify-center">
            <i class="fa fa-leaf text-white"></i>
          </div>
          <div class="h-8 w-8 bg-secondary rounded-md flex items-center justify-center">
            <i class="fa fa-bolt text-white"></i>
          </div>
          <span class="text-xl font-bold text-white">Vite + Vue3</span>
        </div>
      </div>
    </div>
  </footer>

  <!-- JavaScript -->
  <script>
    // 移动端菜单切换
    const menuBtn = document.getElementById('menuBtn')
    const mobileMenu = document.getElementById('mobileMenu')

    menuBtn.addEventListener('click', () => {
      mobileMenu.classList.toggle('hidden')
    })

    // 导航栏滚动效果
    const navbar = document.getElementById('navbar')

    window.addEventListener('scroll', () => {
      if (window.scrollY > 50) {
        navbar.classList.add('shadow-md')
        navbar.classList.remove('shadow-sm')
      } else {
        navbar.classList.remove('shadow-md')
        navbar.classList.add('shadow-sm')
      }
    })

    // 平滑滚动
    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
      anchor.addEventListener('click', function (e) {
        e.preventDefault()

        const targetId = this.getAttribute('href')
        const targetElement = document.querySelector(targetId)

        if (targetElement) {
          window.scrollTo({
            top: targetElement.offsetTop - 80,
            behavior: 'smooth'
          })

          // 关闭移动菜单
          if (!mobileMenu.classList.contains('hidden')) {
            mobileMenu.classList.add('hidden')
          }
        }
      })
    })
  </script>
</body>

</html>